package org.example.learn.javaagent.apply_demo;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;
import org.example.learn.javaagent.apply_demo.plugin.IPlugin;
import org.example.learn.javaagent.apply_demo.plugin.InterceptPoint;
import org.example.learn.javaagent.apply_demo.plugin.PluginFactory;

import java.lang.instrument.Instrumentation;
import java.util.List;

public class Agent {

    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("=====================================");
        AgentBuilder agentBuilder = new AgentBuilder.Default();

        List<IPlugin> pluginList = PluginFactory.plugins;
        for (IPlugin plugin : pluginList) {
            InterceptPoint[] interceptPoints = plugin.buildInterceptPoint();
            for (InterceptPoint point : interceptPoints) {
                // 设置方法匹配规则
                AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, module) -> {
                    builder = builder.visit(Advice.to(plugin.adviceClass()).on(point.buildMethodsMatcher()));
                    return builder;
                };
                // 设置类、方法匹配规则
                agentBuilder = agentBuilder.type(point.buildTypesMatcher()).transform(transformer);
            }
        }
        // 监听
        AgentBuilder.Listener listener = new AgentBuilder.Listener() {
            @Override
            public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }

            @Override
            public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) {
                System.out.println("onTransformation: " + typeDescription);
            }

            @Override
            public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }

            @Override
            public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {

            }

            @Override
            public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }
        };

        agentBuilder.with(listener).installOn(inst);
    }

    public static void premain(String agentArgs) {
        System.out.println("Agent Args: " + agentArgs);
    }
}
